package org.springframework.security.core.userdetails;/* Copyright 2004, 2005, 2006 Acegi Technology Pty Limited
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

import org.springframework.security.core.CredentialsContainer;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.util.Assert;

import java.io.Serializable;
import java.util.*;

/**
 * Models core user information retrieved by a {@link UserDetailsService}.
 * <p>
 * Implemented with value object semantics (immutable after construction, like a
 * <code>String</code>). Developers may use this class directly, subclass it, or
 * write their own {@link UserDetails} implementation from scratch.
 * <p>
 * {@code equals} and {@code hashcode} implementations are based on the
 * {@code username} property only, as the intention is that lookups of the same
 * user principal object (in a user registry, for example) will match where the
 * objects represent the same user, not just when all the properties
 * (authorities, password for example) are the same.
 * 
 * @author Ben Alex
 * @author Luke Taylor
 */
public class User implements UserDetails, CredentialsContainer {
	// ~ Instance fields
	// ================================================================================================
	// private Long id;
	
	private int userId;
	private String password;//userPwd;
	private String loginId;

	// private String logo;
	// private String locale;
	private String menuStr;
	// private TStaff staff;

	private String username;//loginId

	private String userCnName;

	private String deptCd;//部门代码
	private int deptParentId;//部门ID
	private String deptName;//部门名称
	private String identityNo;//身份证

	private String roleIds;//角色id，逗号分割
	private String siteIds;//站点id，逗号分割
	private int personnelId;//用户表Id

	private final Set<GrantedAuthority> authorities;
	private final boolean accountNonExpired;
	private final boolean accountNonLocked;
	private final boolean credentialsNonExpired;
	private final boolean enabled;
	
	private String loginIP; // 登录用户IP
	
	private List<Map<String, Object>> rightList;

	public List<Map<String, Object>> getRightList() {
		return rightList;
	}

	public void setRightList(List<Map<String, Object>> rightList) {
		this.rightList = rightList;
	}


	// ~ Constructors
	// ===================================================================================================


	/**
	 *
	 * @param userId
	 * @param username
	 * @param password
	 * @param menuStr
	 * @param authorities
	 * @param rightList 权限列表
	 * @param deptCd
	 * @param deptParentId
	 * @param enabled
	 * @param accountNonExpired
	 * @param credentialsNonExpired
	 * @param accountNonLocked
	 * @param deptName
	 * @param identityNo
	 */
	public User(int userId, String loginId,String username, String password, String userCnName,String menuStr,
                Collection<? extends GrantedAuthority> authorities, List<Map<String, Object>> rightList,
                String deptCd,int deptParentId,boolean enabled, boolean accountNonExpired,
                boolean credentialsNonExpired, boolean accountNonLocked, String deptName, String identityNo, String roleIds,String siteIds,int personnelId) {

		if (((username == null) || "".equals(username)) || (password == null)) {
			throw new IllegalArgumentException(
					"Cannot pass null or empty values to constructor");
		}
		this.userId=userId;
		this.loginId=loginId;
		this.username = username;
		this.userCnName = userCnName;
		this.password = password;
		this.deptCd=deptCd;
		this.deptParentId=deptParentId;
		this.menuStr = menuStr;
		this.enabled = enabled;
		this.accountNonExpired = accountNonExpired;
        this.credentialsNonExpired = credentialsNonExpired;
        this.accountNonLocked = accountNonLocked;
		this.authorities = Collections
				.unmodifiableSet(sortAuthorities(authorities));
		this.rightList = rightList;
		this.deptName = deptName;
		this.identityNo = identityNo;
		this.roleIds = roleIds;
		this.siteIds = siteIds;
		this.personnelId = personnelId;
	}

	public void eraseCredentials() {
		password = null;
	}

	private static SortedSet<GrantedAuthority> sortAuthorities(
			Collection<? extends GrantedAuthority> authorities) {
		Assert.notNull(authorities,
				"Cannot pass a null GrantedAuthority collection");
		// Ensure array iteration order is predictable (as per
		// UserDetails.getAuthorities() contract and SEC-717)
		SortedSet<GrantedAuthority> sortedAuthorities = new TreeSet<GrantedAuthority>(
				new AuthorityComparator());

		for (GrantedAuthority grantedAuthority : authorities) {
			Assert.notNull(grantedAuthority,
					"GrantedAuthority list cannot contain any null elements");
			sortedAuthorities.add(grantedAuthority);
		}

		return sortedAuthorities;
	}

	private static class AuthorityComparator implements
			Comparator<GrantedAuthority>, Serializable {
		public int compare(GrantedAuthority g1, GrantedAuthority g2) {
			// Neither should ever be null as each entry is checked before
			// adding it to the set.
			// If the authority is null, it is a custom authority and should
			// precede others.
			if (g2.getAuthority() == null) {
				return -1;
			}

			if (g1.getAuthority() == null) {
				return 1;
			}

			return g1.getAuthority().compareTo(g2.getAuthority());
		}
	}

	/**
	 * Returns {@code true} if the supplied object is a {@code User} instance
	 * with the same {@code username} value.
	 * <p>
	 * In other words, the objects are equal if they have the same username,
	 * representing the same principal.
	 */
	@Override
	public boolean equals(Object rhs) {
		if (rhs instanceof User) {
			return username.equals(((User) rhs).username);
		}
		return false;
	}

	/**
	 * Returns the hashcode of the {@code username}.
	 */
	@Override
	public int hashCode() {
		return username.hashCode();
	}

	@Override
	public String toString() {
		StringBuilder sb = new StringBuilder();
        sb.append(super.toString()).append(": ");
		sb.append("LoginId: ").append(this.loginId).append("; ");
        sb.append("Username: ").append(this.username).append("; ");
        sb.append("Password: [PROTECTED]; ");
        sb.append("Enabled: ").append(this.enabled).append("; ");
        sb.append("AccountNonExpired: ").append(this.accountNonExpired).append("; ");
        sb.append("credentialsNonExpired: ").append(this.credentialsNonExpired).append("; ");
        sb.append("AccountNonLocked: ").append(this.accountNonLocked).append("; ");
		sb.append("roleIds: ").append(this.roleIds).append("; ");
		sb.append("siteIds: ").append(this.siteIds).append("; ");
		sb.append("personnelId: ").append(this.personnelId).append("; ");
		if (!authorities.isEmpty()) {
			sb.append("Granted Authorities: ");

			boolean first = true;
			for (GrantedAuthority auth : authorities) {
				if (!first) {
					sb.append(",");
				}
				first = false;

				sb.append(auth);
			}
		} else {
			sb.append("Not granted any authorities");
		}

		return sb.toString();
	}

	public String getIdentityNo() {
		return identityNo;
	}

	public void setIdentityNo(String identityNo) {
		this.identityNo = identityNo;
	}

	public boolean isAccountNonExpired() {
		// TODO Auto-generated method stub
		return accountNonExpired;
	}

	public boolean isAccountNonLocked() {
		// TODO Auto-generated method stub
		return accountNonLocked;
	}

	public boolean isCredentialsNonExpired() {
		// TODO Auto-generated method stub
		return credentialsNonExpired;
	}

	public String getLoginId() {
		return loginId;
	}

	public void setLoginId(String loginId) {
		this.loginId = loginId;
	}

	public int getUserId() {
		return userId;
	}

	public void setUserId(int userId) {
		this.userId = userId;
	}

	public String getPassword() {
		return password;
	}

	public void setPassword(String password) {
		this.password = password;
	}

	public String getUserCnName() {
		return userCnName;
	}

	public void setUserCnName(String userCnName) {
		this.userCnName = userCnName;
	}

	public String getRoleIds() {
		return roleIds;
	}

	public void setRoleIds(String roleIds) {
		this.roleIds = roleIds;
	}

	public String getSiteIds() {
		return siteIds;
	}

	public void setSiteIds(String siteIds) {
		this.siteIds = siteIds;
	}

	public int getPersonnelId() {
		return personnelId;
	}

	public void setPersonnelId(int personnelId) {
		this.personnelId = personnelId;
	}

	public String getDeptCd() {
		return deptCd;
	}

	public void setDeptCd(String deptCd) {
		this.deptCd = deptCd;
	}

	public int getDeptParentId() {
		return deptParentId;
	}

	public void setDeptParentId(int deptParentId) {
		this.deptParentId = deptParentId;
	}

	public String getDeptName() {
		return deptName;
	}

	public void setDeptName(String deptName) {
		this.deptName = deptName;
	}


	public boolean isEnabled() {
		return enabled;
	}

	@Override
	public Collection<GrantedAuthority> getAuthorities() {
		// TODO Auto-generated method stub
		return null;
	}


	public String getUsername() {
		return username;
	}

	public void setUsername(String username) {
		this.username = username;
	}

	public String getLoginIP() {
		return loginIP;
	}

	public void setLoginIP(String loginIP) {
		this.loginIP = loginIP;
	}

	public Map<String,Object> toHashMap(){
		Map<String,Object> map = new HashMap<String,Object>();
		
		map.put("userId", userId);
		map.put("loginId", loginId);
		map.put("loginIP", loginIP);
		map.put("password", password);
		map.put("username", username);
		map.put("userCnName", userCnName);
		map.put("deptCd", deptCd);
		map.put("deptParentId", deptParentId);
		map.put("deptName", deptName);
		map.put("rightList", rightList);
		map.put("authorities", authorities);
		map.put("enabled", enabled);
		map.put("accountNonExpired", accountNonExpired);
		map.put("identityNo", identityNo);
		map.put("roleIds", roleIds);
		map.put("siteIds", siteIds);
		map.put("personnelId", personnelId);
		return map;
	}

}
